package com.hsoft.zhxy.generator;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

public class MyBatisGenerator {

    // 生成文件的存储根路径
    private final static String savePath    = "D:/mybatis-genarator-code/";
    // 生成文件的虚拟项目名
    private final static String projectName = "zhxy-ge3.0-2020";
    // 默认包结构名称
    private final static String packageName = "com.hsoft.zhxy.app";

    /**
     * 根据表自动生成
     * @param tableNames 表名
     */
    public static void generateByTables(DbType dbType, String driver, String dbUrl, String userName, String password, String moduleName, String[] tableNames) {
        // 配置数据源
        DataSourceConfig dataSourceConfig = getDataSourceConfig(dbType, driver, dbUrl, userName, password);
        // 策略配置
        StrategyConfig strategyConfig = getStrategyConfig(tableNames);
        // 全局变量配置
        GlobalConfig globalConfig = getGlobalConfig(false);
        // 包名配置
        PackageConfig packageConfig = getPackageConfig(packageName);
        packageConfig.setModuleName(moduleName);
        // 自定义模板配置
        TemplateConfig templateConfig = getTemplateConfig();
        // 自动生成
        atuoGenerator(dataSourceConfig, strategyConfig, globalConfig, packageConfig, templateConfig);
    }

    /**
     * 返回项目路径
     * @param projectName 项目名
     * @return 项目路径
     */
    private static String getOutputDir(String savePath, String projectName) {
        return savePath + projectName + "/src/main/java/";
    }

    /**
     * 集成
     * @param dataSourceConfig 配置数据源
     * @param strategyConfig 策略配置
     * @param config 全局变量配置
     * @param packageConfig 包名配置
     */
    private static void atuoGenerator(DataSourceConfig dataSourceConfig, StrategyConfig strategyConfig, GlobalConfig config,
            PackageConfig packageConfig, TemplateConfig templateConfig) {
        new AutoGenerator().setGlobalConfig(config).setDataSource(dataSourceConfig).setStrategy(strategyConfig)
                .setPackageInfo(packageConfig).setTemplateEngine(new FreemarkerTemplateEngine()).setTemplate(templateConfig).execute();
    }

    /**
     * 设置包名
     * @param packageName 父路径包名
     * @param packageName 模块名
     * @return PackageConfig 包名配置
     */
    private static PackageConfig getPackageConfig(String packageName) {
        return new PackageConfig().setParent(packageName)
                .setXml("mapper.xml")
                .setMapper("mapper")
                .setController("controller")
                .setService("service")
                .setServiceImpl("service.impl")
                .setEntity("model.entity");
    }

    /**
     * 全局配置
     * @param serviceNameStartWithI false
     * @return GlobalConfig
     */
    private static GlobalConfig getGlobalConfig(boolean serviceNameStartWithI) {
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setBaseColumnList(true).setBaseResultMap(true).setActiveRecord(false)
                // 作者
                .setAuthor("system")
                // 设置输出路径
                .setOutputDir(getOutputDir(savePath, projectName)).setFileOverride(true);
        if (!serviceNameStartWithI) {
            // 设置service名
            globalConfig.setServiceName("%sService");
        }
        return globalConfig;
    }

    /**
     * 策略配置
     * @param tableNames 表名
     * @return StrategyConfig
     */
    private static StrategyConfig getStrategyConfig(String... tableNames) {
        return new StrategyConfig()
                // 全局大写命名 ORACLE 注意
                .setCapitalMode(true)
                // 从数据库表到文件的命名策略
                .setNaming(NamingStrategy.underline_to_camel)
                // 需要生成的的表名，多个表名传数组
                .setInclude(tableNames)
                // 写于父类中的公共字段
//                .setSuperEntityColumns("id")
                // 使用lombok
                .setEntityLombokModel(true)
                // rest风格
                .setRestControllerStyle(true);
    }

    /**
     * 配置数据源
     * @return 数据源配置 DataSourceConfig
     */
    private static DataSourceConfig getDataSourceConfig(DbType dbType, String driver, String dbUrl, String userName, String password) {
        return new DataSourceConfig().setDbType(dbType).setUrl(dbUrl).setUsername(userName).setPassword(password).setDriverName(driver);
    }

    /**
     * 自定义模板配置
     * @return
     */
    private static TemplateConfig getTemplateConfig() {
        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();
        
        // 配置自定义输出模板（如果不配置这些，则会按照官方的配置进行生成）
        //指定自定义模板路径，注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
        templateConfig.setEntity("templates/entity2.java");
        templateConfig.setController("templates/controller2.java");
        templateConfig.setService("templates/service2.java");
        templateConfig.setServiceImpl("templates/serviceImpl2.java");
        templateConfig.setMapper("templates/mapper2.java");//设置为空则代表不需要生成
        templateConfig.setXml(null);//设置为空则代表不需要生成
        
        return templateConfig;
    }

}